package jiang.SensitiveWord;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static jiang.SensitiveWord.CheckSensitiveWords.END_FLAG;
import static jiang.SensitiveWord.CheckSensitiveWords.sensitiveWordsMap;

/**
 * @ClassName SensitiveWordUtil
 * @Description:
 * @Author jiangshitao
 * @Date 2023/10/30
 */
public class SensitiveWordUtil {
    private StringBuilder replaceAll;
    private String encoding = "UTF-8";
    private List<String> arrayList;
    private String fileName;
    public static Set<String> sensitiveWordSet;
    public List<String> sensitiveWordList;

    private SensitiveWordUtil(String fileName) {
        this.fileName = fileName;
    }

    public SensitiveWordUtil() {
    }

    public String filterInfo(String str) throws Exception {
        sensitiveWordSet = new HashSet();
        this.sensitiveWordList = new ArrayList();
        StringBuilder buffer = new StringBuilder(str);
        HashMap<Integer, Integer> hash = new HashMap(this.arrayList.size());

        Integer mapStart;
        label41:
        for(int x = 0; x < this.arrayList.size(); ++x) {
            String temp = (String)this.arrayList.get(x);
            int findIndexSize = 0;
//            int start = 1;

            while(true) {
                int start;
                do {
                    if ((start = buffer.indexOf(temp, findIndexSize)) <= -1) {
                        continue label41;
                    }

                    findIndexSize = start + temp.length();
                    mapStart = (Integer)hash.get(start);
                } while(mapStart != null && (mapStart == null || findIndexSize <= mapStart));

                hash.put(start, findIndexSize);
            }
        }

        Collection<Integer> values = hash.keySet();
        Iterator var11 = values.iterator();

        while(var11.hasNext()) {
            Integer startIndex = (Integer)var11.next();
            mapStart = (Integer)hash.get(startIndex);
            String sensitive = buffer.substring(startIndex, mapStart);
            if (!sensitive.contains("*")) {
                sensitiveWordSet.add(sensitive);
                this.sensitiveWordList.add(sensitive);
            }
        }

        hash.clear();
        return buffer.toString();
    }

    public void initializationWork(String fileName) throws Exception {
        this.arrayList = new ArrayList();
        File file = new File(fileName);
        FileInputStream fileInputStream = new FileInputStream(file);
        InputStreamReader read = new InputStreamReader(fileInputStream, this.encoding);
        BufferedReader bufferedReader = new BufferedReader(read);
        String txt = null;

        while((txt = bufferedReader.readLine()) != null) {
            if (!this.arrayList.contains(txt)) {
                this.arrayList.add(txt);
            }
        }

        fileInputStream.close();
        bufferedReader.close();
        read.close();
    }

    public static Set<String> checkSensitiveWord2(String str, Set<String> sensitiveWords) throws Exception {
        // 这里参数是敏感词目录，如果报错可以替换成自己的目录
        SensitiveWordUtil sw = new SensitiveWordUtil(CheckSensitiveWords.class.getResource("/filter/keyword.txt").getPath());
        sw.initializationWork(sw.getFileName());
        sw.filterInfo(str.replace("\r\n", "").replace("\n", "").replace(" ", ""));
        return sensitiveWordSet;
    }

    public static Set<String> checkSensitiveWord(String str) throws Exception {
        // 这里参数是敏感词目录，如果报错可以替换成自己的目录
        SensitiveWordUtil sw = new SensitiveWordUtil(CheckSensitiveWords.class.getResource("/filter/keyword.txt").getPath());
        sw.initializationWork(sw.getFileName());
        sw.filterInfo(str.replace("\r\n", "").replace("\n", "").replace(" ", ""));
        return sensitiveWordSet;
    }

    public static String sensitiveWords(String msgs) {
        if (msgs.contains("20001")) {
            Pattern pattern = Pattern.compile("\\[.*?\\]");
            Matcher matcher = pattern.matcher(msgs);
            if (matcher.find()) {
                return matcher.group(0);
            }
        }

        return "";
    }

    public StringBuilder getReplaceAll() {
        return this.replaceAll;
    }

    public void setReplaceAll(StringBuilder replaceAll) {
        this.replaceAll = replaceAll;
    }

    public List<String> getArrayList() {
        return this.arrayList;
    }

    public void setArrayList(List<String> arrayList) {
        this.arrayList = arrayList;
    }

    public String getEncoding() {
        return this.encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public String getFileName() {
        return this.fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    static void initSensitiveWordsMap(Set<String> sensitiveWords){
        if(sensitiveWords==null||sensitiveWords.isEmpty()){
            throw new IllegalArgumentException("Senditive words must not be empty!");
        }
        sensitiveWordsMap=new HashMap<>(sensitiveWords.size());
        String currentWord;
        Map<Object,Object> currentMap;
        Map<Object,Object> subMap;
        Iterator<String> iterator = sensitiveWords.iterator();
        while (iterator.hasNext()){
            currentWord=iterator.next();
            if(currentWord==null||currentWord.trim().length()<2){  //敏感词长度必须大于等于2
                continue;
            }
            currentMap=sensitiveWordsMap;
            for(int i=0;i<currentWord.length();i++){
                char c=currentWord.charAt(i);
                subMap=(Map<Object, Object>) currentMap.get(c);
                if(subMap==null){
                    subMap=new HashMap<>();
                    currentMap.put(c,subMap);
                    currentMap=subMap;
                }else {
                    currentMap= subMap;
                }
                if(i==currentWord.length()-1){
                    //如果是最后一个字符，则put一个结束标志，这里只需要保存key就行了，value为null可以节省空间。
                    //如果不是最后一个字符，则不需要存这个结束标志，同样也是为了节省空间。
                    currentMap.put(END_FLAG,null);
                }
            }
        }
    }

    public Set<String> getSensitiveWords(String text, String matchType){
        if(text==null||text.trim().length()==0){
            throw new IllegalArgumentException("The input text must not be empty.");
        }
        Set<String> sensitiveWords=new HashSet<>();
        for(int i=0;i<text.length();i++){
            int sensitiveWordLength = getSensitiveWordLength(text, i, matchType);
            if(sensitiveWordLength>0){
                String sensitiveWord = text.substring(i, i + sensitiveWordLength);
                sensitiveWords.add(sensitiveWord);
                if(matchType.equals("最小匹配规则")){
                    break;
                }
                i=i+sensitiveWordLength-1;
            }
        }
        return sensitiveWords;
    }

    public int getSensitiveWordLength(String text, int startIndex, String matchType) {
        if (text == null || text.trim().length() == 0) {
            throw new IllegalArgumentException("The input text must not be empty.");
        }
        char currentChar;
        Map<Object, Object> currentMap = sensitiveWordsMap;
        int wordLength = 0;
        boolean endFlag = false;
        for (int i = startIndex; i < text.length(); i++) {
            currentChar = text.charAt(i);
            Map<Object, Object> subMap = (Map<Object, Object>) currentMap.get(currentChar);
            if (subMap == null) {
                break;
            } else {
                wordLength++;
                if (subMap.containsKey(END_FLAG)) {
                    endFlag = true;
                    if (matchType.equals("最小匹配规则")) {
                        break;
                    } else {
                        currentMap = subMap;
                    }
                } else {
                    currentMap = subMap;
                }
            }
        }
        if (!endFlag) {
            wordLength = 0;
        }
        return wordLength;
    }
}
